const fs = require('fs')
const path = require('path')
const express = require('express')
const expressJwt = require('express-jwt')
const multer = require('multer')
const uuid = require('uuid')
const joi = require('joi')


/************************ 引入自定义模块 *************************/
const constants = require('./config/constants')
const rescode = require('./config/rescode')
const { dirName } = require('./utils/fileUitls')
const userRouter = require('./router/userRoter')


// 创建 express 实例
const app = express()


/************************ 注册全局中间件 *************************/
// 为 res 挂载全局处理函数，用于返回 JSON 格式数据
app.use((req, res, next) => {
  // code 为 0000 时表示成功；非 0000 表示失败
  res.r = function (err = '成功', code = '0000', data) {
    if (typeof err === 'object' && !(err instanceof Error)) {
      data = err
      err = '成功'
    }
    res.send({
      // 状态
      code,
      // 状态描述
      msg: err instanceof Error ? err.message : err,
      // 返回数据
      data
    })
  }
  next()
})

// 注册解析 JSON 格式数据的中间件。请求处理中通过 req.body 负责接受前端发送的数据
app.use(express.json())
// 注册解析 application/x-www-form-urlencoded 格式的表单数据的中间件。请求处理中通过 req.body 负责接受前端发送的数据
app.use(express.urlencoded({ extended: true }))
// 注册解析 TOKEN，并指定哪些接口无须指定。获取用户信息时用 req.auth。注意老版本使用 req.user
app.use(expressJwt.expressjwt({ secret: constants.TOKEN_SECRET_KEY, algorithms: ["HS256"] }).unless({ path: ['/api/user/reg'] }))


/************************ 注册路由 *************************/
app.use('/api/user', userRouter)


/************************ 文件处理 *************************/
const storage = multer.diskStorage({
  // 文件存放目录
  destination: (req, file, cb) => {
    const fileDir = './public/files/' + dirName(file.mimetype)
    fs.access(fileDir, fs.constants.F_OK, (err) => {
      if (err) {
        fs.mkdirSync(fileDir, { recursive: true })
      }
      // cb 回调函数(错误对象，上传存放目录)
      cb(null, fileDir)
    })
  },
  // 文件名称
  filename: (req, file, cb) => {
    // cb 回调函数(错误对象，文件名称)
    cb(null, uuid.v4().replaceAll("-", "") + "_" + Date.now() + path.extname(file.originalname))
  }
})

const upload = multer({ storage })
app.post('/api/upload', upload.single('file'), (req, res) => {
  return res.r({ path: req.file.path })
})
app.post('/api/uploads', upload.array('file', 5), (req, res) => {
  console.log(req.files)
  return res.r()
})


// 注册错误中间件，捕获整个项目的异常(错误中间件必须在路由之后进行挂载)
app.use((err, req, res, next) => {
  console.error('系统发生了异常', err)

  // 捕获身份认证失败的错误
  if (err.name === 'UnauthorizedError') {
    return res.r('Token为空或已失效', rescode.TOKEN_EXPIRES_ERROR)
  }

  if (err instanceof joi.ValidationError) {
    return res.r(err, rescode.REQ_VALID_ERROR)
  }

  res.r(err.message)
})


// 绑定服务端口并启动服务
app.listen(3000, () => {
  console.log("服务已成功启动...")
})